package com.fiap.activities;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.Chronometer.OnChronometerTickListener;
import android.widget.TextView;

import com.fiap.event.GPSEvent;
import com.fiap.functions.UserFunctions;
import com.fiap.model.Statistics;
import com.fiap.model.User;
import com.fiap.service.GPSService;
import com.fiap.service.RunService;
import com.fiap.service.SocialService;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

public class GPSActivity extends BaseActivity {
    
	// TAG used for log
	private static final String TAG = "GPSActivity";
	//private static final String ServletUrl="http://ec2-107-21-178-180.compute-1.amazonaws.com:8080/TesteServlet/TesteServlet";
	//private static final String ServletUrl="http://10.0.2.2:8080/TesteServlet/TesteServlet";
	private static final String ServletUrl="http://10.0.2.2/testephp/liverun.php";
	private Bundle bundle;

	private GoogleMap map;
	private Marker actualMarker;
	private LatLng gpsUserPosition;
	private DialogInterface.OnClickListener dialogClickListener;
	
	// View fields
	private TextView txtVelocidade;
    private TextView txtVelocidadeMaxima;
    private TextView txtVelocidadeMedia;
    private TextView txtDistancia;
	private TextView txtCalorias;
	private Button btnIniciar;
	private Chronometer chronometer;
	private Button btnParar;
	
    // Singleton classes
	private GPSService gpsService;
	private RunService corrida;
	private Statistics statistics;
	
    // Activity variables
	long timeWhenStopped = 0;

	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);       
		super.onCreate(savedInstanceState);
		
		SocialService.init(getApplicationContext());
		
		setContentView(R.layout.gps);
		bundle = new Bundle();
		
		gpsService = GPSService.getInstance();	
		corrida = RunService.getInstance();
		
		map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
		        .getMap();
		
		map.getUiSettings().setMyLocationButtonEnabled(false);
		map.setMyLocationEnabled(true);
	    map.getUiSettings().setCompassEnabled(true);
	    
	    SharedPreferences preferences = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
	    String userName = preferences.getString("userName", "");
		
	    try {
			MapsInitializer.initialize(getApplicationContext());
	    } catch (GooglePlayServicesNotAvailableException ex){
	    	// User doesn't have Google Play Services Installed. Look for the latest version for Download and install it.
	    	Log.d("GPSActivity", "Android Maps Problem");
			backToInfo(null);
	    }
	    
		prepararTela();
		
		gpsService.setEvent(new GPSEvent() {
			public void onGPSUpdate(Location location) {
				if (gpsService.isStarted() && 
						corrida.isRunning()) {
					gpsUserPosition = new LatLng(gpsService.getLastLocation().getLatitude(), 
							  gpsService.getLastLocation().getLongitude());
					sendPosition(location);
					corrida.addPosition(gpsUserPosition);
					if (actualMarker != null){
						actualMarker.remove();
					} 
					actualMarker = map.addMarker(new MarkerOptions().position(gpsUserPosition)
							.title("João")
							.snippet("Runners porra!")
							.icon(BitmapDescriptorFactory.fromResource(R.drawable.personagem_mapa_001)));
					map.moveCamera(CameraUpdateFactory.newLatLngZoom(gpsUserPosition, 15));
					
					PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.RED);
					for(int i = 0 ; i < corrida.getArrayPositionsRoute().size() ; i++) {          
						rectLine.add(corrida.getArrayPositionsRoute().get(i));
					}
					
					map.addPolyline(rectLine);
					
					statistics = Statistics.getInstance(gpsService.getLastLocation().getLatitude(), 
							  gpsService.getLastLocation().getLongitude());
					
					statistics.update(location.getLatitude(), location.getLongitude(), location.getSpeed());
					
					txtVelocidade.setText(String.format("%.2f km/h", statistics.getVelocidade())); //km/h
					txtVelocidadeMaxima.setText(String.format("%.2f km/h", statistics.getVelocidadeMaxima()));//km/h
					txtVelocidadeMedia.setText(String.format("%.2f km/h", statistics.getVelocidadeMedia())); //km/h
					txtDistancia.setText(String.format("%.2f", statistics.getTotalDistance()));
					txtCalorias.setText(String.format("%.2f cal", statistics.getCalorias()));
				} else {
					btnIniciar.setEnabled(true);
					txtVelocidade.setText("Pronto");	
				}
			}
		});
		gpsService.onActivityCreated(this);
		corrida.onActivityCreated();
	}
	
	@Override
	protected void onStart() {
		super.onStart();
		gpsService.onActivityStarted();
		corrida.onActivityStarted();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		gpsService.onActivityResumed();
		corrida.onActivityResumed();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		gpsService.onActivityPaused();
		corrida.onActivityPaused();
	}
	
	@Override
	protected void onStop() {
		super.onStop();
		gpsService.onActivityStopped();
		corrida.onActivityStopped();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		gpsService.onActivityDestroy();
		Log.d("Teste", "Destroying activity");
	}
	
	private void prepararTela() {
		txtDistancia		= (TextView)findViewById(R.id.text_gps_distancia);
		txtVelocidade		= (TextView)findViewById(R.id.text_gps_velocidade);
    	txtVelocidadeMaxima	= (TextView)findViewById(R.id.text_gps_velocidadeMaxima);
    	txtVelocidadeMedia	= (TextView)findViewById(R.id.text_gps_velocidadeMedia);
    	txtCalorias			= (TextView)findViewById(R.id.text_gps_calorias);
    	btnIniciar			= (Button)findViewById(R.id.button_gps_iniciar);
    	chronometer 		= (Chronometer) findViewById(R.id.chronometer);
    	btnParar			= (Button)findViewById(R.id.button_stop);
    	
    	chronometer.setText("00:00:00");
    	
    	btnIniciar.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				if (btnIniciar.getText().equals(getString(R.string.pausar))) {
					btnIniciar.setText(getString(R.string.continuar));
					corrida.stop();
					updateLiveRun();
					pauseChronometer(chronometer);
//					irParaTelaPostagem();
				} else if(btnIniciar.getText().equals(getString(R.string.iniciar))){
					chronometer.setBase(SystemClock.elapsedRealtime());
					chronometer.start();
					corrida.start();
					btnIniciar.setText(getString(R.string.pausar));
				} else {
					chronometer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
					chronometer.start();
					corrida.start();
					btnIniciar.setText(getString(R.string.pausar));
				}
			}
		});
    	
    	btnParar.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View view) {
				corrida.stop();
				updateLiveRun();
				chronometer.stop();
//				showShareDialog();
				displayRunSumary();
			}
		});
    	
    	chronometer.setOnChronometerTickListener(new OnChronometerTickListener() {
    	    public void onChronometerTick(Chronometer cArg) {
    	        long t = SystemClock.elapsedRealtime() - cArg.getBase();
    	        cArg.setText(DateFormat.format("kk:mm:ss", t));
    	    }
    	});
    	
    	dialogClickListener = new DialogInterface.OnClickListener() {
    	    @Override
    	    public void onClick(DialogInterface dialog, int which) {
    	        switch (which){
    	        case DialogInterface.BUTTON_POSITIVE:
    	        	share();
    	            break;

    	        case DialogInterface.BUTTON_NEGATIVE:
    	        	backToInfo(null);
    	            break;
    	        }
    	    }
    	};
    	
	}
	protected void pauseChronometer(Chronometer chronometer) {
		timeWhenStopped = chronometer.getBase() - SystemClock.elapsedRealtime();
		chronometer.stop();
	}

	protected void share() {
		String message = "Acabei de correr " + txtDistancia.getText().toString() + 
				"km em " + chronometer.getText().toString() + "h!";
		UserFunctions userFunction = new UserFunctions();
        User user = userFunction.getUser(getApplicationContext());
        
        userFunction.postOnRunners(user.getId(), message);
		backToInfo(null);
	}

	public void showShareDialog() {
    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
    	builder.setMessage("Deseja compartilhar sua corrida?").setPositiveButton("Sim", dialogClickListener)
    	    .setNegativeButton("Não", dialogClickListener).show();
	}
	
	public void displayRunSumary(){
		// Save a snapshot of the run.
		SnapshotReadyCallback callback = new SnapshotReadyCallback() {
            Bitmap bitmap;

            @Override
            public void onSnapshotReady(Bitmap snapshot) {
                bitmap = snapshot;
                try {
                	   String cacheDir = getApplicationContext().getCacheDir().toString();
                	   String fileName = cacheDir + "/user01_run_map.png";
//                	   File outputDir = getApplicationContext().getCacheDir();
//                	   File outputFile = File.createTempFile("user01_run_map", "png", outputDir);
                       FileOutputStream out = new FileOutputStream(fileName);
                       bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
                } catch (Exception e) {
                       e.printStackTrace();
                }
            }
        };
        
        map.snapshot(callback);
        
		Intent runSummary = new Intent(getApplicationContext(),
				RunSummary.class);
		startActivity(runSummary);
	}
	
	private void irParaTelaPostagem() {
		bundle.remove(Constants.PARAM_CONVITE);
		bundle.remove(Constants.PARAM_MENASGEM);
		
		bundle.putSerializable(Constants.PARAM_CONVITE, Boolean.FALSE);
		bundle.putSerializable(Constants.PARAM_MENASGEM, 
				String.format("Acabei de percorrer %.2f km em %.2f minutos, " +
						"com uma velocidade média de %.2f km/h.",
						statistics.getTotalDistance(),
						statistics.getTotalTime(),
						statistics.getVelocidadeMedia()));
		
		iniciarActivity(LoginFacebookActivity.class, bundle);
	}

	private void irParaTelaConvite() {
		bundle.remove(Constants.PARAM_CONVITE);
		bundle.remove(Constants.PARAM_MENASGEM);
		
		bundle.putSerializable(Constants.PARAM_CONVITE, Boolean.TRUE);
		
		iniciarActivity(ConviteActivity.class, bundle);
	}
	
	private class SendPositionTask extends AsyncTask<String, Void, String> {
	    @Override
	    protected String doInBackground(String... params) {
	    	String response = "";
	    	String url = params[0];
	    	String latitude = params[1];
	    	String longitude = params[2];
	    	String email = params[3];
	    	String userid = params[4];
	    	Log.w(TAG, "latitude from Location: " + latitude);
	    	Log.w(TAG, "longitude from Location: " + longitude);
		        
	    	url += "?";
	    			
	        List<NameValuePair> nameValuePairs = new LinkedList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("latitude", latitude));
	        nameValuePairs.add(new BasicNameValuePair("longitude", longitude));
	        nameValuePairs.add(new BasicNameValuePair("email", email));
	        nameValuePairs.add(new BasicNameValuePair("userid", userid));
	        nameValuePairs.add(new BasicNameValuePair("tag", "sendPosition"));
	        
	        String paramString = URLEncodedUtils.format(nameValuePairs, "UTF-8");
	        		
	        url += paramString;
	        Log.w(TAG, "url = " + url);
	        DefaultHttpClient client = new DefaultHttpClient();
	        HttpGet httpGet = new HttpGet(url);
	        
	        
	        try {
	            HttpResponse execute = client.execute(httpGet);
	            InputStream content = execute.getEntity().getContent();

	            BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
	            String s = "";
	            while ((s = buffer.readLine()) != null) {
	            	response += s;
		        }

	        } catch (Exception e) {
	          e.printStackTrace();
	        }
	      return response;
	    }

//	    @Override
//	    protected void onPostExecute(String result) {
//	    	webServiceTextView.setText(result);
//	    }
	  }
	
	public void sendPosition(Location location) {
		Log.w(TAG, "-LAT" + location.getLatitude());
		Log.w(TAG, "-LON" + location.getLongitude());
		
		DecimalFormat decimalFormatter = new DecimalFormat("0.######");

        String latitude = decimalFormatter.format(location.getLatitude());
        String longitude = decimalFormatter.format(location.getLongitude());
        String userid = "1";
		Log.w(TAG, "--LAT" + latitude);
		Log.w(TAG, "--LON" + longitude);
		String email = "leandro.alsberg@gmail.com";
	    SendPositionTask task = new SendPositionTask();
	    task.execute(new String[] { ServletUrl, latitude, longitude, email, userid });

	}
	
	private class UpdateLiveRunTask extends AsyncTask<String, Void, String> {
	    @Override
	    protected String doInBackground(String... params) {
	    	String response = "";
	    	String url = params[0];
	    	String email = params[1];
	    	String userid = params[2];
	    	String status = params[3];
		        
	    	url += "?";
	    			
	        List<NameValuePair> nameValuePairs = new LinkedList<NameValuePair>();
	        nameValuePairs.add(new BasicNameValuePair("status", status));
	        nameValuePairs.add(new BasicNameValuePair("email", email));
	        nameValuePairs.add(new BasicNameValuePair("userid", userid));
	        nameValuePairs.add(new BasicNameValuePair("tag", "updateStatus"));
	        
	        String paramString = URLEncodedUtils.format(nameValuePairs, "UTF-8");
	        		
	        url += paramString;
	        Log.w(TAG, "url = " + url);
	        DefaultHttpClient client = new DefaultHttpClient();
	        HttpGet httpGet = new HttpGet(url);
	        
	        try {
	            HttpResponse execute = client.execute(httpGet);
	            InputStream content = execute.getEntity().getContent();

	            BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
	            String s = "";
	            while ((s = buffer.readLine()) != null) {
	            	response += s;
		        }

	        } catch (Exception e) {
	          e.printStackTrace();
	        }
	      return response;
	    }
	  }
	
	public void updateLiveRun() {
		Log.w(TAG, "updateLiveRun start");
		
        String userid = "1";
		String email = "leandro.alsberg@gmail.com";
	    UpdateLiveRunTask task = new UpdateLiveRunTask();
	    task.execute(new String[] { ServletUrl, email, userid, "0" });

	}

	 public void goToMap (View v) {
		 	Intent i  = new Intent(MainActivity.ACAO_EXIBIR_SAUDACAO);
		 	i.addCategory(MainActivity.CATEGORIA_SAUDACAO);
		 	i.putExtra(MainActivity.EXTRA_POSICAO_USUARIO, gpsService.getLastLocation().getLatitude() + 
		 																							   ";" +
		 													gpsService.getLastLocation().getLongitude());
			startActivity(i);
	    }
	 
	 public void backToInfo (View v) {
		 Intent i = new Intent(getApplicationContext(), MainMenuActivity.class);
		 startActivity(i);
	 }
}